# -*- coding: utf-8 -*-
import sys, os
try:
        import pygtk
        pygtk.require("2.0")
except:
        pass
try:
        import gtk
        import gtk.glade
except:
        sys.exit(1)
from simpledcpp.gui.base import gtk_lock_required
from simpledcpp.core.base import DCPPPart, DCPPEvent
from simpledcpp.gui.widgets.list import ConnectionsTree
from threading import Lock
import time
from simpledcpp.gui.HumanReadableSize import HRS
class ConnectionManager(DCPPPart):
	def __init__(self, parent):
		DCPPPart.__init__(self, parent)
		self._connections = {} # store all connections by cid <-> iter
		self._tthdict = {} # store all points by tth <-> iter, (cid1,cid2,cid3) # Cid of abstract connections is -1
		self._prepare = {} # store all first-parth data from connection
		self.HRS = HRS()
		self.Events.Subscribe("ON_NEW_CONNECTION", self.add)
		self.Events.Subscribe("ON_DESTROY_CONNECTION", self.remove)
		self.Events.Subscribe("ON_CONNECTION_UPDATE",self.update)
		self.Events.Subscribe("QUEUE_UPDATED", self.qupdate)
                menu_items = (
                ("/_" + _("Stop"),"stop",self._destroy, 0 , None),
                )
		self.tree = ConnectionsTree(menu_items)
		self.tree.setSortable(0)
		self._widget = gtk.ScrolledWindow()
		self._widget.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		self._widget.add(self.tree.widget)
		self._widget.show()
		self.parent.wtree.get_widget("ConnectionsBox").pack_start(self._widget)
		self.parent.wtree.get_widget("ConnectionsBox").show()
		self.status_bar()

	def _destroy(self, *args, **kwargs):
		cid = self.tree.selected_rows[6]
		if cid == -1:
			tth = self.tree.selected_rows[5]
			if self._tthdict.has_key(tth):
				for scid in self._tthdict[tth][1]:
					 self.Event(DCPPEvent("DESTROY_CONNECTION",(scid,)))
		else:
			self.Event(DCPPEvent("DESTROY_CONNECTION",(cid,)))
		self.status_bar()

	@gtk_lock_required
	def add(self, Event):
		# Fill prepare data.
		con = Event.userdata[0]
		self._prepare[con.cid] = [con._n, con.direction]
		self.status_bar()

	def status_bar(self, *args, **kwargs):
		count = len(self._connections)
		uspeed = 0
		dspeed = 0
		try:
			for i in self._connections:
				stock = self.tree.treestore.get_value(self._connections[i],0)
				speed = self.tree.treestore.get_value(self._connections[i],2)
				speed = int(speed)
				if stock == gtk.STOCK_GO_DOWN:
					dspeed = dspeed + speed
				else:
					uspeed = uspeed + speed
			string = _("Connections count: %s    Download speed: %s    Upload speed: %s")%(count, self.HRS.byteToHuman(dspeed), self.HRS.byteToHuman(uspeed))

			self.Event(DCPPEvent("GSB",(string, )))
		except:
			print sys.exc_info()
			
	@gtk_lock_required
	def remove(self, Event):
		# remove data from prepare, connection, from tthdict
		con = Event.userdata[0]
		try:
			tid = self._connections.pop(con.cid)
		except:
			return
		self._prepare.pop(con.cid)
		# Try check tth of connection
		tth = self.tree.treestore.get_value(tid, 5)
#		if len(tth) == 39 and self._tthdict.has_key(tth):
#			if con.cid in self._tthdict[tth][1]:
#				self._tthdict[tth][1].remove(con.cid)
# If connection change TTH during live, code up of this line don't work.
# New version (may be slow, when many connections used.)
		if len(tth) == 39:
			for tthd in self._tthdict:
				if con.cid in self._tthdict[tthd][1]:
					self._tthdict[tthd][1].remove(con.cid)
					tth = tthd # dirty hack for next lines.
		self.tree.remove(tid)
		if self._tthdict.has_key(tth):
			if len(self._tthdict[tth][1]) == 0:
				self.tree.remove(self._tthdict[tth][0])
				self._tthdict.pop(tth)
		self.status_bar()

	@gtk_lock_required
	def update(self, Event):
		#print "UPDATE"
		try:
			cid, speed, progress, filename, filelength, tth, nickname = Event.userdata
		except:
			print sys.exc_info()
		# If it's new connection, create it in _connections
		if not self._connections.has_key(cid):
                        if not self._prepare.has_key(cid):
                                        return
			if self._prepare[cid][1] == 'Download':
                                stock_id = gtk.STOCK_GO_DOWN
                        else:
          	              stock_id = gtk.STOCK_GO_UP

			# if it's connection with tth and point already exist
			if self._tthdict.has_key(tth):
				if not self._prepare.has_key(cid):
					return
				self._connections[cid] = self.tree.append((stock_id, 0, speed, filename, nickname, tth, cid),
						parent = self._tthdict[tth][0])
				self._tthdict[tth][1].append(cid)
			# If connections with tth and point does'nt exists
			elif (not self._tthdict.has_key(cid)) and len(tth) == 39:
				self._tthdict[tth] = [self.tree.append((stock_id, 0, "", filename, "", tth, -1)), [cid,]]
				self._connections[cid] = self.tree.append((stock_id, 0, speed, filename, nickname, tth, cid),
                                                parent = self._tthdict[tth][0])
			# connection without tth
			else:
				self._connections[cid] = self.tree.append((stock_id, 0, speed, filename, nickname, tth, cid))
		try:
			status = int(progress)*100/int(filelength)
		except:
			status = 0
		try:
			status = int(status)
			try:
				self.tree.update(self._connections[cid], 1, status)
				self.tree.update(self._connections[cid], 2, speed)
				self.tree.update(self._connections[cid], 3, filename)
				self.tree.update(self._connections[cid], 4, nickname)
				self.tree.update(self._connections[cid], 5, tth)
			except:
				pass
		except:
			print sys.exc_info()
		self.recalculate_speed(tth)
		self.status_bar()

	def recalculate_speed(self, tth):
		if self._tthdict.has_key(tth):
			summary_speed = 0
			for cid in self._tthdict[tth][1]:
				if self._connections.has_key(cid):
					speed = self.tree.treestore.get_value(self._connections[cid], 2)
					summary_speed = summary_speed + int(speed)
			self.tree.update(self._tthdict[tth][0], 2, self.HRS.byteToHuman(summary_speed))
#		pass
	@gtk_lock_required
	def qupdate(self, Event):
		task = Event.userdata[0]
		if self._tthdict.has_key(task.TTH):
			self.tree.update(self._tthdict[task.TTH][0], 1, int(task.segment.percent()))
